package com.javabi.codegenerator.java.object.factory.method;

import com.javabi.codegenerator.java.model.JavaModel;
import com.javabi.codegenerator.java.model.bean.JavaModelBean;
import com.javabi.codegenerator.java.model.serializer.JavaModelDataSerializer;
import com.javabi.codegenerator.java.object.factory.FactoryType;
import com.javabi.codeobject.java.block.codeblock.IJavaCodeLines;
import com.javabi.codeobject.java.block.codeblock.JavaCodeLines;
import com.javabi.codeobject.java.block.method.constructor.JavaConstructor;
import com.javabi.codeobject.java.type.IJavaType;

public class FactoryConstructor extends JavaConstructor {

	public FactoryConstructor(IJavaType type, JavaModel model, FactoryType factoryType) {
		super(type);

		setConstructorContents(model, factoryType);
	}

	private void setConstructorContents(JavaModel model, FactoryType factoryType) {
		IJavaCodeLines code = new JavaCodeLines();

		code.emptyLine();
		code.line("// Mappings by id");
		for (JavaModelBean bean : model.getBeanList()) {
			putById(code, bean, factoryType);
		}

		code.emptyLine();
		code.line("// Mappings by name");
		for (JavaModelBean bean : model.getBeanList()) {
			putByName(code, bean, factoryType);
		}

		setContents(code);
	}

	private void putByName(IJavaCodeLines code, JavaModelBean bean, FactoryType type) {
		switch (type) {
			case EXECUTABLE_BEAN:
				if (bean.isExecutable()) {
					putByName(code, bean, bean.getType());
				}
				break;
			case DATA_SERIALIZER:
				if (bean.hasSerializer()) {
					JavaModelDataSerializer serializer = bean.getDataSerializer();
					putByName(code, bean, serializer.getType());
				}
				break;
		}
	}

	private void putById(IJavaCodeLines code, JavaModelBean bean, FactoryType type) {
		switch (type) {
			case EXECUTABLE_BEAN:
				if (bean.isExecutable()) {
					putById(code, bean, bean.getType());
				}
				break;
			case DATA_SERIALIZER:
				if (bean.hasSerializer()) {
					JavaModelDataSerializer serializer = bean.getDataSerializer();
					putById(code, bean, serializer.getType());
				}
				break;
		}
	}

	private void putByName(IJavaCodeLines code, JavaModelBean bean, IJavaType classType) {
		IJavaType beanType = bean.getType();
		getReferences().add(beanType);
		getReferences().add(classType);
		String beanName = beanType.getSimpleName();
		String className = classType.getSimpleName();
		code.line("objectMap.put(\"" + beanName + "\", " + className + " .class);");
	}

	private void putById(IJavaCodeLines code, JavaModelBean bean, IJavaType classType) {
		IJavaType beanType = bean.getType();
		getReferences().add(beanType);
		getReferences().add(classType);
		String beanName = beanType.getSimpleName();
		String className = classType.getSimpleName();
		code.line("objectMap.put(" + beanName + ".SERIALIZATION_ID, " + className + " .class);");
	}

}
